package com.example.rabbitmqsimple.consumer;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

/**
 * RabbitMQ 简单模式（Hello World）的消息消费者
 * 演示最基础的消息接收流程：连接到RabbitMQ服务器，监听指定队列并消费消息
 */
public class Consumer_HelloWorld {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1. 创建连接工厂，用于配置RabbitMQ连接信息
        ConnectionFactory factory = new ConnectionFactory();

        // 2. 设置RabbitMQ服务器连接参数
        factory.setHost("localhost");      // 服务器主机地址（本地）
        factory.setPort(5672);            // 服务器端口（默认AMQP端口）
        factory.setVirtualHost("/");      // 虚拟主机（默认）
        factory.setUsername("guest");     // 用户名（默认）
        factory.setPassword("guest");     // 密码（默认）

        // 3. 通过工厂创建与RabbitMQ服务器的连接
        Connection connection = factory.newConnection();

        // 4. 创建信道（Channel），所有操作都通过信道进行
        Channel channel = connection.createChannel();

        // 5. 声明要消费的队列（确保队列存在，与生产者队列匹配）
        // 参数说明：
        // - queue: 队列名称 "hello_world"
        // - durable: 是否持久化（true表示队列在服务器重启后仍存在）
        // - exclusive: 是否排他（false表示允许其他连接访问）
        // - autoDelete: 是否自动删除（false表示不自动删除）
        // - arguments: 额外参数（null表示使用默认配置）
        channel.queueDeclare("hello_world", true, false, false, null);

        // 6. 创建消费者对象，并重写消息处理方法
        Consumer consumer = new DefaultConsumer(channel) {
            /**
             * 当接收到消息时，会自动调用此方法
             * @param consumerTag 消费者标签，用于标识消费者
             * @param envelope 消息信封，包含交换机、路由键、消息ID等信息
             * @param properties 消息属性（如优先级、过期时间等）
             * @param body 消息体（字节数组形式）
             * @throws IOException 处理消息时可能抛出的IO异常
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                // 打印消息相关信息
                System.out.println("consumerTag: " + consumerTag);          // 消费者标签
                System.out.println("Exchange: " + envelope.getExchange());  // 消息来自的交换机
                System.out.println("RoutingKey: " + envelope.getRoutingKey()); // 消息的路由键
                System.out.println("properties: " + properties);            // 消息属性
                System.out.println("body: " + new String(body));            // 消息内容（转换为字符串）
            }
        };

        // 7. 开始消费指定队列的消息
        // 参数说明：
        // - queue: 要消费的队列名称 "hello_world"
        // - autoAck: 是否自动确认（true表示消息接收后自动确认，RabbitMQ会删除消息）
        // - callback: 消息处理回调（即上面创建的consumer对象）
        channel.basicConsume("hello_world", true, consumer);
    }
}